import com.sun.org.apache.xpath.internal.SourceTree;

import javax.swing.text.html.Option;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Test {


    public static void test1(){
        Integer[] nums = {1, 2, 3, 4, 5} ;
        List<Integer> res = Arrays.stream(nums).map(i -> i*i).collect(Collectors.toList()) ;
        System.out.println(res.toString());
    }

    public static void test2(){
        List<Integer> num1 = Arrays.asList(1,2,3) ;
        List<Integer> num2 = Arrays.asList(4,5) ;

        List res1 = num1.stream().map(i -> num2.stream().map(j -> new int[]{i,j})).collect(Collectors.toList()) ;

        List<int[]> res2 = num1.stream().flatMap(i -> num2.stream().map(j -> new int[]{i,j})).collect(Collectors.toList()) ;

        List<int[]> res3 = num1.stream().flatMap(i -> num2.stream().filter(j -> (i+j)%3 == 0).map(j -> new int[]{i,j})).collect(Collectors.toList());


    }

    public static void test3(){
        List<Integer> num1 = Arrays.asList(1,2,3) ;
        int sum = num1.stream().reduce(0, (i,j) -> i+j) ;

        sum = num1.stream().reduce(0, Integer::sum) ;

        Optional<Integer> sumObj = num1.stream().reduce(Integer::sum) ;
        sum = sumObj.get() ;
    }

    public static void test4(){
        List<Integer> num1 = Arrays.asList(1,2,3) ;

        int max = num1.stream().reduce(0,Integer::max) ;
        System.out.println(max);

         max = num1.stream().max((i,j)-> i-j).get() ;
        System.out.println(max);
    }

    private static List<Integer> num1 = Arrays.asList(1,2,3) ;

    public static void test5(){
        long count = num1.stream().count() ;
        System.out.println(count);

        num1.stream().map(i -> 1).reduce(0,Integer::sum) ;
    }

    public static void test6(){
        int a = 5 ;
        List<int[]> res1 = IntStream.rangeClosed(0,100).filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).boxed().map(b->new int[]{a,b, (int) Math.sqrt(a*a+b*b)}).collect(Collectors.toList()) ;

        List<Integer> test = IntStream.rangeClosed(0,100).filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).map(b->b+1).boxed().collect(Collectors.toList());

        List<int[]> res = IntStream.rangeClosed(0,100).filter(b->Math.sqrt(a*a + b*b)%1 == 0).mapToObj(b-> new int[]{a,b,(int)Math.sqrt(a*a + b*b)}).collect(Collectors.toList()) ;

        List<Person> persons = IntStream.rangeClosed(1,3).boxed().map(i -> new Person("fsh",i)).collect(Collectors.toList()) ;



        Stream<int[]> res_auto = IntStream.rangeClosed(0,100).boxed().flatMap(aa -> IntStream.rangeClosed(0,100).filter(b->Math.sqrt( aa*aa+ b*b) % 1 == 0).mapToObj(b -> new int[]{aa, b, (int)Math.sqrt(aa*aa + b*b)})) ;

        res_auto.forEach(i -> System.out.println(i[0] + "," + i[1] + "," + i[2]));
    }

    public static void test7(){


        Stream<int[]> res = IntStream.rangeClosed(1,100).boxed().flatMap(a ->
                IntStream.rangeClosed(a, 100)
                        .filter(b -> Math.sqrt(a*a + b*b) % 1 == 0)
                        .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a*a + b*b)})
        ) ;

        res.forEach(i -> System.out.println(i[0] + "," + i[1] + "," + i[2]));
    }

    public static void test8(){
        Stream<int[]> streams = IntStream.rangeClosed(0,100).boxed().flatMap(a -> IntStream.rangeClosed(a, 100).filter(b -> a+b == 2*b+1).mapToObj(b -> new int[]{a,b})) ;
        streams.forEach(i -> System.out.println(i[0] + "," + i[1]));
    }

    public static void test9(){
        Stream.iterate(new int[]{0,1}, t-> new int[]{t[1], t[0]+t[1]}).limit(20).forEach(i ->System.out.println(i[0] + "," + i[1]));
    }

    public static void test10(){
        IntStream.generate(()->1).limit(10).forEach(i -> System.out.println(i));
    }

    public static void test11(){
        IntSupplier intSupplier = new IntSupplier() {
            int previous = 0 ;
            int current = 1 ;
            @Override
            public int getAsInt() {
                int old = previous ;
                previous = current ;
                current = old + current ;
                return old ;
            }
        };

        IntStream.generate(intSupplier::getAsInt).limit(20).forEach(i-> System.out.println(i));
    }

    static class Person{
        private String name ;
        private int age ;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public Person() {
        }
    }

    public static void test12(){
        IntStream.range(1,199).boxed().collect(Collectors.toList()) ;
    }

    public static void test13(){
        Comparator<Integer> comparator = Comparator.comparing(Integer::intValue) ;
        Optional<Integer> max = IntStream.range(1,500).boxed().collect(Collectors.maxBy(comparator)) ;

        Optional<Integer> min = IntStream.rangeClosed(1,500).boxed().collect(Collectors.minBy(Comparator.comparing(Integer::intValue))) ;

        int sum = IntStream.rangeClosed(1,3).boxed().collect(Collectors.summingInt(i -> i.intValue())) ;

        double avg = IntStream.rangeClosed(1,500).boxed().collect(Collectors.averagingInt(i -> i.intValue())) ;

        System.out.println(max);
    }

    public static void test14(){
        List<Integer> res = IntStream.range(0,100).boxed().collect(Collectors.toList()) ;

        System.out.println(res.toString());
    }

    public static void test15(){
        IntStream.range(0,100).noneMatch(i -> 100 % i == 0) ;

    }

    class ToListCollector<T> implements Collector<T, List<T>, List<T>>{

        @Override
        public Supplier<List<T>> supplier() {
            return ArrayList::new ;
        }

        @Override
        public BiConsumer<List<T>, T> accumulator() {
            return List::add;
        }

        @Override
        public BinaryOperator<List<T>> combiner() {
            return (list1, list2) -> {
                list1.addAll(list2) ;
                return list1 ;
            };
        }

        @Override
        public Function<List<T>, List<T>> finisher() {
            return Function.identity() ;
        }

        @Override
        public Set<Characteristics> characteristics() {
            return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH, CONCURRENT));
        }
    }

    public static void test16(){
        IntStream.range(0,100).boxed().collect(ArrayList::new, List::add, List::addAll) ;
    }

    public static boolean isPrime(int n){
        return IntStream.rangeClosed(2,n-1).limit((long)Math.floor(Math.sqrt((double)n))-1)
                .noneMatch(i->n%i == 0) ;
    }

    public static Map<Boolean, List<Integer>> partitionPrimes(int n){
        return IntStream.range(0,n).boxed()
                .collect(Collectors.partitioningBy(candidate -> isPrime(candidate))) ;

    }

    public static void main(String[] args) {
        test14() ;
    }
}
